#include "AnimationShader.h"
#include "IObject.h"

AnimationShader::AnimationShader(VertexLayout vl)
{
	Init("skin.fx","VS","vs_4_0","PS","ps_4_0", vl);
}

AnimationShader::~AnimationShader(void)
{	
	boneMatrixBuffer->Release();
	g_pCBChangesEveryFrame->Release();
	g_pSamplerLinear->Release();
}

HRESULT AnimationShader::Init(const char* effectName,const char* VsName, const char* vsVersion, const char* PsName,const char* psVersion, VertexLayout vl, const char* GsName ,const char* GsVersion , D3D11_SO_DECLARATION_ENTRY declaration[] , int nElements ,UINT* stride , UINT numStrides)
{
	HRESULT hr = S_OK;
	hr = IShader::Init(effectName,VsName,vsVersion,PsName,psVersion,vl);
	CheckError(hr);

	// Create the constant buffers
	D3D11_BUFFER_DESC bd;
    ZeroMemory( &bd, sizeof(bd) );
    bd.Usage = D3D11_USAGE_DEFAULT;                    
    bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
    bd.CPUAccessFlags = 0;    
    bd.ByteWidth = sizeof(ASChangesEveryFrame);	
	hr = EngineStuff::EGraphicsDevice->CreateBuffer( &bd, NULL, &g_pCBChangesEveryFrame);
    CheckError(hr);

	bd.ByteWidth = sizeof(XMMATRIX) * MAXBONES;
	bd.Usage = D3D11_USAGE_DYNAMIC;
	bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
	bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
	hr = EngineStuff::EGraphicsDevice->CreateBuffer( &bd, NULL, &boneMatrixBuffer);
    CheckError(hr);

    // Create the sample state
    D3D11_SAMPLER_DESC sampDesc;
    ZeroMemory( &sampDesc, sizeof(sampDesc) );
    sampDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
    sampDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
    sampDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
    sampDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
    sampDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
    sampDesc.MinLOD = 0;
    sampDesc.MaxLOD = D3D11_FLOAT32_MAX;
	hr = EngineStuff::EGraphicsDevice->CreateSamplerState( &sampDesc, &g_pSamplerLinear );
    CheckError(hr);

	return hr;
}

void AnimationShader::SetShaderOnDevice(RenderableObject obj)
{	 
	D3D11_MAPPED_SUBRESOURCE subr;	
	ZeroMemory(&subr,sizeof(subr));	

	EngineStuff::EImediateDeviceContext->Map(boneMatrixBuffer,0,D3D11_MAP_WRITE_DISCARD ,NULL,&subr);
	
	memcpy(subr.pData,obj.IOBJECT->GetMesh()->AbsoluteBone,sizeof(XMMATRIX) * MAXBONES);	

	EngineStuff::EImediateDeviceContext->Unmap(boneMatrixBuffer,0);


    EngineStuff::EImediateDeviceContext->UpdateSubresource( g_pCBChangesEveryFrame, 0, NULL, &cbChangesEveryFrame, 0, 0 );	
	
    EngineStuff::EImediateDeviceContext->VSSetConstantBuffers( 0, 1, &g_pCBChangesEveryFrame );
	
	EngineStuff::EImediateDeviceContext->VSSetConstantBuffers( 1, 1, &boneMatrixBuffer);    
	
	ID3D11ShaderResourceView* texture = obj.IOBJECT->GetMesh()->GetTexture(TextureTypes::Diffuse);
	EngineStuff::EImediateDeviceContext->PSSetShaderResources(0, 1, &texture );
    EngineStuff::EImediateDeviceContext->PSSetSamplers( 0, 1, &g_pSamplerLinear );

	IShader::SetShaderOnDevice(obj);
}

void AnimationShader::Update(RenderableObject obj,Camera* camera)
{		
		XMStoreFloat4x4(&cbChangesEveryFrame.Projection , XMMatrixTranspose( camera->getProjectionMatrix() ));
		XMStoreFloat4x4(&cbChangesEveryFrame.View , XMMatrixTranspose(camera->getViewMatrix()));		
		XMStoreFloat4x4(&cbChangesEveryFrame.World, XMMatrixTranspose(*obj.IOBJECT->GetMesh()->Transformation  * *obj.IOBJECT->GetPhysicObject()->GetWorldTransformation() ));		
}
